1 module unit_threaded.randomized.random;
2
3 /** This type will generate a $(D Gen!T) for all passed $(D T...).
4 Every call to $(D genValues) will call $(D gen) of all $(D Gen) structs
5 present in $(D values). The member $(D values) can be passed to every
6 function accepting $(D T...).
7 */
8 struct RndValueGen(T...) {
9 import std.meta : staticMap;
10 import std.random : Random;
11
12 /* $(D Values) is a collection of $(D Gen) types created through
13 $(D ParameterToGen) of passed $(T ...).
14 */
15 static if (is(typeof(T[0]) == string[])) {
16 alias generators = T[1 .. $];
17 string[] parameterNames = T[0];
18 } else {
19 alias generators = T;
20 string[T.length] parameterNames;
21 }
22
23 alias Values = staticMap!(ParameterToGen, generators);
24
25 /// Ditto
26 Values values;
27
28 /* The constructor accepting the required random number generator.
29 Params:
30 rnd = The required random number generator.
31 */
32 this(Random* rnd) @safe {
33 this.rnd = rnd;
34 }
35
36 this(ref Random rnd) {
37 this.rnd = &rnd;
38 }
39
40 /* The random number generator used to generate new value for all
41 $(D values).
42 */
43 Random* rnd;
44
45 /** A call to this member function will call $(D gen) on all items in
46 $(D values) passing $(D the provided) random number generator
47 */
48 void genValues() {
49 assert(rnd !is null);
50 foreach (ref it; this.values) {
51 it.gen(*this.rnd);
52 }
53 }
54
55 void toString(scope void delegate(const(char)[]) sink) {
56 import std.format : formattedWrite;
57
58 foreach (idx, ref it; values) {
59 formattedWrite(sink, "'%s' = %s ", parameterNames[idx], it);
60 }
61 }
62 }
63
64 /** A template that turns a $(D T) into a $(D Gen!T) unless $(D T) is
65 already a $(D Gen) or no $(D Gen) for given $(D T) is available.
66 */
67 template ParameterToGen(T) {
68 import unit_threaded.randomized.gen : isGen, Gen;
69
70 static if (isGen!T)
71 alias ParameterToGen = T;
72 else static if (is(T : GenASCIIString!(S), S...))
73 alias ParameterToGen = T;
74 else {
75 static assert(__traits(compiles, Gen!T), "ParameterToGen does not handle " ~ T.stringof);
76 alias ParameterToGen = Gen!T;
77 }
78 }